﻿' ******************************************************************************
' ** 
' **  Yahoo! Managed
' **  Written by Marius Häusler 2011
' **  It would be pleasant, if you contact me when you are using this code.
' **  Contact: YahooFinanceManaged@gmail.com
' **  Project Home: http://code.google.com/p/yahoo-finance-managed/
' **  
' ******************************************************************************
' **  
' **  Copyright 2011 Marius Häusler
' **  
' **  Licensed under the Apache License, Version 2.0 (the "License");
' **  you may not use this file except in compliance with the License.
' **  You may obtain a copy of the License at
' **  
' **    http://www.apache.org/licenses/LICENSE-2.0
' **  
' **  Unless required by applicable law or agreed to in writing, software
' **  distributed under the License is distributed on an "AS IS" BASIS,
' **  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
' **  See the License for the specific language governing permissions and
' **  limitations under the License.
' ** 
' ******************************************************************************

Imports System.Configuration
Namespace YahooManaged.Finance.Support

    ''' <summary>
    ''' Stores default world market informations
    ''' </summary>
    ''' <remarks></remarks>
    Public Class WorldMarket
        Private Shared ReadOnly mHelper As New MyHelper

        Private Shared mCurrencies() As CurrencyInfo
        Private Shared mCountries() As CountryInfo
        Private Shared mStockExchanges As New List(Of StockExchange)

        ''' <summary>
        ''' All default currencies.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared ReadOnly Property DefaultCurrencies() As CurrencyInfo()
            Get
                Return mCurrencies
            End Get
        End Property
        ''' <summary>
        ''' All default countries.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared ReadOnly Property DefaultCountries() As CountryInfo()
            Get
                Return mCountries
            End Get
        End Property

        ''' <summary>
        ''' The default stock exchanges. Is a reference for getting informations by setting the id of StockExchange or YahooID.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared ReadOnly Property DefaultStockExchanges() As List(Of StockExchange)
            Get
                Return mStockExchanges
            End Get
        End Property

        ''' <summary>
        ''' A list of all available indices
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared ReadOnly Property AllFinanceIndices() As YIndexID()
            Get
                Dim lst As New List(Of Support.YIndexID)
                For Each cnt As CountryInfo In DefaultCountries
                    lst.AddRange(cnt.Indices)
                Next
                Return lst.ToArray
            End Get
        End Property


        Shared Sub New()
            mCurrencies = GetDefaultCurrencies()
            mCountries = GetDefaultCountries()
            mStockExchanges.AddRange(GetDefaultStockExchanges())
            FillCountriesWithIndices()
        End Sub



        ''' <summary>
        ''' Loads a list of default currencies from market.xml
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Function GetDefaultCurrencies() As CurrencyInfo()
            Dim currencies As New List(Of CurrencyInfo)
            Dim xmlDoc As New XmlDocument
            xmlDoc.LoadXml(My.Resources.market)
            Dim curs = xmlDoc.SelectNodes("//Resources/Currencies/Currency")
            For Each curNode As XmlNode In curs
                currencies.Add(New CurrencyInfo(curNode.Attributes("ID").Value, curNode.Attributes("Name").Value))
            Next
            Return currencies.ToArray
        End Function
        ''' <summary>
        ''' Loads as list of default countries from market.xml
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Function GetDefaultCountries() As CountryInfo()
            Dim countries As New List(Of CountryInfo)

            Dim xmlDoc As New XmlDocument
            xmlDoc.LoadXml(My.Resources.market)
            Dim cntNodes = xmlDoc.SelectNodes("//Resources/Countries/Country")
            Dim convCulture = New System.Globalization.CultureInfo("en-US")
            If cntNodes IsNot Nothing AndAlso cntNodes.Count > 0 Then

                For Each cntNode As XmlNode In cntNodes
                    For cnt As Country = 0 To Country.VN
                        If cnt.ToString = cntNode.Attributes("ID").Value Then
                            Dim cntCur As CurrencyInfo = Nothing
                            Dim curID As String = cntNode.Attributes("Currency").Value
                            For Each cur As CurrencyInfo In DefaultCurrencies
                                If cur.ID.ToString = curID Then
                                    cntCur = cur
                                    Exit For
                                End If
                            Next cur

                            Dim dstNodes = cntNode.SelectNodes("DaylightSavingTimes/DST")
                            Dim dstList As New List(Of DaylightSavingTime)
                            For Each dstNode As XmlNode In dstNodes
                                Dim dstStart As DateTime = Convert.ToDateTime(dstNode.Attributes("Start").Value, convCulture)
                                Dim dstEnd As DateTime = Convert.ToDateTime(dstNode.Attributes("End").Value, convCulture)
                                dstList.Add(New DaylightSavingTime(dstStart, dstEnd))
                            Next
                            countries.Add(New CountryInfo(cnt, cntNode.Attributes("Name").Value, cntCur, dstList.ToArray))
                            Exit For
                        End If
                    Next cnt
                Next cntNode
            End If

            Return countries.ToArray
        End Function
        ''' <summary>
        ''' Loads a list of default stock exchanges from market.xml
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Function GetDefaultStockExchanges() As StockExchange()
            Dim lst As New List(Of StockExchange)

            Dim xmlDoc As New XmlDocument
            xmlDoc.LoadXml(My.Resources.market)
            Dim exchanges = xmlDoc.SelectNodes("//Resources/StockExchanges/StockExchange")

            If exchanges IsNot Nothing AndAlso exchanges.Count > 0 Then
                For Each exchangeNode As XmlNode In exchanges

                    Dim seID As String = exchangeNode.Attributes("ID").Value
                    Dim seSuffix As String = exchangeNode.Attributes("Suffix").Value
                    Dim seName = exchangeNode.Attributes("Name").Value

                    Dim seCountry As CountryInfo = Nothing
                    Dim ctrID As String = exchangeNode.Attributes("Country").Value
                    For Each ctr In DefaultCountries
                        If ctr.ID.ToString = ctrID Then
                            seCountry = ctr
                            Exit For
                        End If
                    Next ctr

                    'TradingTimeInfo
                    Dim seDelayMinutes = Convert.ToInt32(exchangeNode.Attributes("DelayMinutes").Value)
                    Dim seRelativeToUTC = Convert.ToInt32(exchangeNode.Attributes("UtcOffsetStandardTime").Value)
                    Dim seOpeningTimeLocal = Convert.ToDateTime(exchangeNode.Attributes("OpeningTimeLocal").Value)
                    Dim seClosingTimeLocal = Convert.ToDateTime(exchangeNode.Attributes("ClosingTimeLocal").Value)
                    Dim seTradingSpan As TimeSpan = seClosingTimeLocal - seOpeningTimeLocal

                    Dim seTradingDaysList As New List(Of DayOfWeek)
                    Dim trdDays As String = exchangeNode.Attributes("TradingDays").Value
                    For Each day As String In trdDays.Split(","c)
                        Select Case day
                            Case "Mo" : seTradingDaysList.Add(DayOfWeek.Monday)
                            Case "Tu" : seTradingDaysList.Add(DayOfWeek.Tuesday)
                            Case "We" : seTradingDaysList.Add(DayOfWeek.Wednesday)
                            Case "Th" : seTradingDaysList.Add(DayOfWeek.Thursday)
                            Case "Fr" : seTradingDaysList.Add(DayOfWeek.Friday)
                            Case "Sa" : seTradingDaysList.Add(DayOfWeek.Saturday)
                            Case "Su" : seTradingDaysList.Add(DayOfWeek.Sunday)
                        End Select
                    Next day

                    Dim seDaylightSavingTimes() As DaylightSavingTime = Nothing
                    If seCountry IsNot Nothing Then seDaylightSavingTimes = seCountry.DaylightSavingTimes

                    Dim seTradingTimeInfo As New TradingTimeInfo(seDelayMinutes, seTradingDaysList.ToArray, Nothing, seOpeningTimeLocal, seTradingSpan, seRelativeToUTC, seDaylightSavingTimes)

                    Dim se As New StockExchange(seID, seSuffix, seName, seCountry, seTradingTimeInfo)

                    If exchangeNode.Attributes("Tags") IsNot Nothing Then
                        Dim val As String = exchangeNode.Attributes("Tags").Value
                        If val <> String.Empty Then se.Tags.AddRange(val.Split(","c))
                    End If

                    lst.Add(se)
                Next exchangeNode

            End If

            Return lst.ToArray
        End Function
        ''' <summary>
        ''' Loads default market information from market.xml
        ''' </summary>
        ''' <remarks></remarks>
        Public Shared Sub FillCountriesWithIndices()

            Dim xmlDoc As New XmlDocument
            xmlDoc.LoadXml(My.Resources.market)

            Dim countryNodes = xmlDoc.SelectNodes("//Resources/Countries/Country")

            For Each countryNode As XmlNode In countryNodes

                Dim ctr As CountryInfo = Nothing

                Dim ctrIDStr As String = countryNode.Attributes("ID").InnerText
                For Each defaultCtr As CountryInfo In DefaultCountries
                    If defaultCtr.ID.ToString = ctrIDStr Then
                        ctr = defaultCtr
                        Exit For
                    End If
                Next

                If ctr IsNot Nothing Then
                    ctr.Indices.Clear()
                    Dim indexNodes = countryNode.SelectNodes("Indices/Index")
                    For Each indexNode As XmlNode In indexNodes
                        If indexNode.Name = "Index" Then
                            Dim name As String = indexNode.Attributes("Name").InnerText
                            Dim id As String = indexNode.Attributes("ID").InnerText

                            Dim seStr As String = indexNode.Attributes("StockExchange").InnerText
                            Dim se As StockExchange = Nothing
                            For Each defaultExc As StockExchange In mStockExchanges
                                If defaultExc.ID = seStr Then
                                    se = defaultExc
                                    Exit For
                                End If
                            Next

                            ctr.Indices.Add(New YIndexID(id) With {.Name = name, .StockExchange = se})
                        End If
                    Next indexNode
                End If

            Next

        End Sub



        Public Shared Function GetDefaultCurrencyByID(ByVal id As String) As CurrencyInfo
            For Each cur In DefaultCurrencies
                If cur.ID = id Then
                    Return cur
                End If
            Next
            Return Nothing
        End Function



        Public Shared Function GetDefaultCountry(ByVal cnt As Country) As CountryInfo
            For Each defaultCnt In DefaultCountries
                If defaultCnt.ID = cnt Then
                    Return defaultCnt
                End If
            Next
            Return Nothing
        End Function

        ''' <summary>
        '''  Tries to return a StockExchange by StockExchange ID string.
        ''' </summary>
        ''' <param name="id">The non-case sensitive ID of the stock exchange. E.g. "DJI" or "gEr"</param>
        ''' <returns>The confirmed stock exchange or null.</returns>
        ''' <remarks></remarks>
        Public Shared Function GetStockExchangeByID(ByVal id As String) As StockExchange
            If WorldMarket.DefaultStockExchanges IsNot Nothing And id <> String.Empty Then
                Dim n As String = id.ToUpper
                For Each se As StockExchange In WorldMarket.DefaultStockExchanges()
                    If se.ID = id Then
                        Return se
                    End If
                Next
            End If
            Return Nothing
        End Function
        ''' <summary>
        ''' Tries to return a StockExchange by an YID String.
        ''' </summary>
        ''' <param name="suffix">The non-case sensitive ID or Suffix of ID. E.g. "BAS.DE" or ".DE"</param>
        ''' <returns>The confirmed stock exchange or null.</returns>
        ''' <remarks></remarks>
        Public Shared Function GetStockExchangeBySuffix(ByVal suffix As String) As StockExchange
            If WorldMarket.DefaultStockExchanges IsNot Nothing And suffix <> String.Empty Then
                Dim index As Integer = suffix.LastIndexOf("."c)
                If index >= 0 And suffix.Length >= index Then
                    Dim suffStr As String = suffix.Substring(index, suffix.Length - index).ToUpper
                    For Each se As StockExchange In WorldMarket.DefaultStockExchanges()
                        If se.Suffix = suffStr Then Return se
                    Next
                End If
            End If
            Return Nothing
        End Function
        ''' <summary>
        ''' Tries to return a StockExchange by the StockExchange's name
        ''' </summary>
        ''' <param name="name">A non-case sensitive name or part of name of a stock exchange. The first name that contains the string will be returned.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Function GetStockExchangeByName(ByVal name As String) As StockExchange
            If WorldMarket.DefaultStockExchanges IsNot Nothing And name <> String.Empty Then
                Dim n As String = name.ToLower
                For Each se As StockExchange In WorldMarket.DefaultStockExchanges()
                    If se.Name.ToLower.IndexOf(n) > -1 Then
                        Return se
                    Else
                        For Each tag In se.Tags
                            If n = tag.ToLower Then Return se
                        Next
                    End If
                Next
            End If
            Return Nothing
        End Function


    End Class

End Namespace